package middleware

import (
	"ginblog/utils"
	"ginblog/utils/errmsg"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"time"
)

// 密钥的参数
var JwtKey = []byte(utils.JwtKey)

// 接受参数的结构体
type MyClaims struct {
	Id int  `json:"id"`
	jwt.StandardClaims
}

var code int

// 生成token
func SetToken(id int)(string,int)  {
	expireTime :=time.Now().Add(30 * 24 * time.Hour) // 过期时间24个小时 乘以 30 ,30天过期
	SetClaims := MyClaims{
		Id:       id,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(), // 转为时间戳
			Issuer: "ginblog",
		},
	}


	reqClain := jwt.NewWithClaims(jwt.SigningMethodHS256,SetClaims)
	token,err := reqClain.SignedString(JwtKey)
	if err != nil {
		return "",errmsg.ERROR
	}
	return token,errmsg.SUCCSE
}

// 验证token
func CheckToken(token string)(*MyClaims, int)  {
	setToken,_:= jwt.ParseWithClaims(token,&MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return JwtKey,nil
	})
	if key,_:= setToken.Claims.(*MyClaims); setToken.Valid{
		return key,errmsg.SUCCSE
	}else{
		return nil,errmsg.ERROR
	}


}

// jwt中间件
func JwtToken() gin.HandlerFunc{
	return func(c *gin.Context) {
		tokenHerder := c.Request.Header.Get("Authorization")

		if tokenHerder == ""{
			code = errmsg.ERROR_TOKEN_EXIST
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrorMsg(code),
			})
			c.Abort()
			return
		}
		checkToken := strings.SplitN(tokenHerder," ",2)
		if len(checkToken) != 2 && checkToken[0] != "Bearer" {
			code = errmsg.ERROR_TOKEN_TYPE_WRONG
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrorMsg(code),
			})
			c.Abort()
			return
		}
		key,tCode := CheckToken(checkToken[1])
		if tCode == errmsg.ERROR{
			code = errmsg.ERROR_TOKEN_WRONG
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrorMsg(code),
			})
			c.Abort()
			return
		}
		if time.Now().Unix() > key.ExpiresAt {
			code = errmsg.ERROR_TOKEN_RUNTIME
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrorMsg(code),
			})
			c.Abort()
			return
		}

		c.Set("userid",key.Id)
		c.Next()
	}
}

